home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / security / log_tcp_6.0alpha.shar / shell_cmd.c < prev    next >
C/C++ Source or Header  |  1993-07-02  |  3KB  |  115 lines

  1.  /*
  2.   * shell_cmd() takes a shell command template and performs %a (host
  3.   * address), %c (client info), %h (host name or address), %d (daemon name),
  4.   * %p (process id) and %u (user name) substitutions. The result is executed
  5.   * by a /bin/sh child process, with standard input, standard output and
  6.   * standard error connected to /dev/null.
  7.   * 
  8.   * Diagnostics are reported through syslog(3).
  9.   * 
  10.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  11.   */
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#) shell_cmd.c 1.3 93/03/07 22:47:39";
  15. #endif
  16.  
  17. /* System libraries. */
  18.  
  19. #include <sys/types.h>
  20. #include <sys/param.h>
  21. #include <signal.h>
  22. #include <stdio.h>
  23. #include <syslog.h>
  24.  
  25. extern char *strncpy();
  26. extern void closelog();
  27. extern void exit();
  28.  
  29. /* Local stuff. */
  30.  
  31. #include "log_tcp.h"
  32.  
  33. /* Forward declarations. */
  34.  
  35. static void do_child();
  36.  
  37. /* shell_cmd - expand %<char> sequences and execute shell command */
  38.  
  39. void    shell_cmd(string, daemon, client)
  40. char   *string;
  41. char   *daemon;
  42. struct from_host *client;
  43. {
  44.     char    cmd[BUFSIZ];
  45.     int     child_pid;
  46.     int     wait_pid;
  47.     int     daemon_pid = getpid();
  48.  
  49.     /*
  50.      * Most of the work is done within the child process, to minimize the
  51.      * risk of damage to the parent.
  52.      */
  53.  
  54.     switch (child_pid = fork()) {
  55.     case -1:                    /* error */
  56.     syslog(LOG_ERR, "fork: %m");
  57.     break;
  58.     case 00:                    /* child */
  59.     percent_x(cmd, sizeof(cmd), string, daemon, client, daemon_pid);
  60.     do_child(daemon, cmd);
  61.     /* NOTREACHED */
  62.     default:                    /* parent */
  63.     while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
  64.          /* void */ ;
  65.     }
  66. }
  67.  
  68. /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
  69.  
  70. static void do_child(myname, command)
  71. char   *myname;
  72. char   *command;
  73. {
  74.     char   *error = 0;
  75.     int     tmp_fd;
  76.  
  77.     /*
  78.      * SunOS 4.x may send a SIGHUP to grandchildren if the child exits first.
  79.      * Sessions and process groups make old and grown-up programmers tear out
  80.      * what little hair is left and run away crying.
  81.      */
  82.  
  83.     signal(SIGHUP, SIG_IGN);
  84.  
  85.     /*
  86.      * Close a bunch of file descriptors. The Ultrix inetd only passes stdin,
  87.      * but other inetd implementations set up stdout as well. Ignore errors.
  88.      */
  89.  
  90.     closelog();
  91.     for (tmp_fd = 0; tmp_fd < 10; tmp_fd++)
  92.     (void) close(tmp_fd);
  93.  
  94.     /* Set up new stdin, stdout, stderr, and exec the shell command. */
  95.  
  96.     if (open("/dev/null", 2) != 0) {
  97.     error = "open /dev/null: %m";
  98.     } else if (dup(0) != 1 || dup(0) != 2) {
  99.     error = "dup: %m";
  100.     } else {
  101.     (void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
  102.     error = "execl /bin/sh: %m";
  103.     }
  104.  
  105.     /* We can reach the following code only if there was an error. */
  106.  
  107. #ifdef LOG_MAIL
  108.     (void) openlog(myname, LOG_PID, FACILITY);
  109. #else
  110.     (void) openlog(myname, LOG_PID);
  111. #endif
  112.     syslog(LOG_ERR, error);
  113.     exit(0);
  114. }
  115.